﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SecureCookie.Implementation.Helper
{
    /// <summary>
    /// Class containing 'higher order' helper functions
    /// </summary>
    static class HigherOrderFunctions
    {
        /// <summary>
        /// Tries to execute a codeblock, when it fails with an exception, the exception is being passed
        /// to the beforeSwallowBlock parameter. The beforeSwallowBlock may throw exceptions but those will NOT
        /// be rethrowed. Hence the name TryAndSwallow.
        /// </summary>
        /// <param name="tryBlock"></param>
        /// <param name="beforeSwallowBlock"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This function is specifically made to swallow every type of exception")]
        internal static void TryAndSwallow(Action tryBlock, Action<Exception> beforeSwallowBlock)
        {
            try
            {
                tryBlock();
            }
            catch (Exception ex)
            {
                try
                {
                    beforeSwallowBlock(ex);
                }
                catch { }
            }
        }
        /// <summary>
        /// Performs an action on a sequence of items. Comparable with the List<typeparamref name="T"/>.ForEach
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items"></param>
        /// <param name="action"></param>
        internal static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
        {
            foreach (var x in items)
                action(x);
        }
        /// <summary>
        /// Wraps a Try/Catch for an action on a sequence of items
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items"></param>
        /// <param name="tryAction"></param>
        /// <param name="catchAction"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This is by design, this higher order function catches explicitely all exceptions")]
        internal static void ForEachTryCatch<T>(this IEnumerable<T> items, Action<T> tryAction, Action<T, Exception> catchAction)
        {
            foreach (var x in items)
                try
                {
                    tryAction(x);
                }
                catch (Exception ex)
                {
                    catchAction(x, ex);
                }
        }
        /// <summary>
        /// Performs an action with possible side effects on a sequence of items
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        internal static IEnumerable<T> Do<T>(this IEnumerable<T> items, Action<T> action)
        {
            foreach (var x in items)
            {
                action(x);
                yield return x;
            }

        }
    }
}
